In [ ]:
import json
import random
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from sklearn.metrics import confusion_matrix
In [ ]:
conf_threshold = 0.6
save_csv = True
save_plots = True

Json Daten Megedetectron lesen¶

In [ ]:
train_features_label = pd.read_csv("../eda/train_features_label.csv", index_col='id')

mega_json = json.load(open('train_features_output.json'))
mega_json.keys()
Out[ ]:
dict_keys(['images', 'detection_categories', 'info'])
In [ ]:
dict_detection_cat = mega_json['detection_categories']
dict_detection_cat
Out[ ]:
{'1': 'animal', '2': 'person', '3': 'vehicle'}
In [ ]:
mega_detector_info = mega_json['info']
mega_detector_info
Out[ ]:
{'detection_completion_time': '2023-04-01 11:21:59',
 'format_version': '1.2',
 'detector': 'md_v5a.0.0.pt',
 'detector_metadata': {'megadetector_version': 'v5a.0.0',
  'typical_detection_threshold': 0.2,
  'conservative_detection_threshold': 0.05}}
In [ ]:
df_images = pd.DataFrame(mega_json["images"])
df_images = df_images.reset_index(drop=True)
df_images
Out[ ]:
file max_detection_conf detections
0 ZJ000000.jpg 0.690 [{'category': '1', 'conf': 0.00851, 'bbox': [0...
1 ZJ000001.jpg 0.813 [{'category': '1', 'conf': 0.813, 'bbox': [0.5...
2 ZJ000002.jpg 0.612 [{'category': '1', 'conf': 0.00643, 'bbox': [0...
3 ZJ000003.jpg 0.686 [{'category': '1', 'conf': 0.00796, 'bbox': [0...
4 ZJ000004.jpg 0.476 [{'category': '1', 'conf': 0.476, 'bbox': [0.5...
... ... ... ...
16483 ZJ016483.jpg 0.000 []
16484 ZJ016484.jpg 0.528 [{'category': '1', 'conf': 0.00831, 'bbox': [0...
16485 ZJ016485.jpg 0.151 [{'category': '1', 'conf': 0.151, 'bbox': [0.4...
16486 ZJ016486.jpg 0.264 [{'category': '1', 'conf': 0.0139, 'bbox': [0....
16487 ZJ016487.jpg 0.896 [{'category': '1', 'conf': 0.0178, 'bbox': [0....

16488 rows × 3 columns

In [ ]:
# several bbox per image possible
df_images['detections'][0]
Out[ ]:
[{'category': '1', 'conf': 0.00851, 'bbox': [0.9229, 0.8129, 0.07708, 0.1555]},
 {'category': '1', 'conf': 0.69, 'bbox': [0.1093, 0.5888, 0.0802, 0.1851]}]

Daten in geeignetes Format bringen¶

In [ ]:
def read_megadetector_json(path_json:str = 'train_features_output.json'):
    mega_json = json.load(open(path_json))

    df_images = pd.DataFrame(mega_json["images"])
    df_images = df_images.reset_index(drop=True)
    return df_images

def get_clean_dataframe_from_json(treshold:float=0.6, save_csv=False, filter_th=True):
    '''
    filter: filters bbox below treshold if true
    '''

    df_images = read_megadetector_json()

    df_images_detections = df_images['detections'].apply(pd.Series, dtype='object')
    #display(df_images_detections.head(2))

    df_images_clean = df_images.merge(df_images_detections, left_index=True, right_index=True).drop(columns='detections')
    #display(df_images_clean.head(2))

    df_images_clean = df_images_clean.melt(id_vars=['file', 'max_detection_conf']).sort_values('file')
    #display(df_images_clean)

    # remove nan values 
    df_images_clean = df_images_clean.dropna(subset='value')
    df_images_clean = df_images_clean.drop(columns='variable')

    # expand category, conf, bbox
    df_cat_conf_bbox = df_images_clean['value'].apply(pd.Series, dtype='object')
    df_images_clean = df_images_clean.merge(df_cat_conf_bbox, left_index=True, right_index=True).drop(columns='value')

    # take only detections for max detection conf
    df_images_clean = df_images_clean[df_images_clean['max_detection_conf'] == df_images_clean['conf']]
    df_images_clean = df_images_clean.reset_index(drop=True)

    # leftjoin clean data
    df_images_clean = pd.merge(df_images['file'], df_images_clean, on='file', how='left')

    # cast datatypes
    df_images_clean['category'] = df_images_clean['category'].astype('category')
    df_images_clean['category'] = df_images_clean['category'].replace(dict_detection_cat)

    # change index to image name
    df_images_clean['image_name'] = [image.replace('.jpg', '') for image in df_images_clean['file']]
    df_images_clean.index = df_images_clean['image_name']
    df_images_clean = df_images_clean.drop(columns='image_name')

    if filter_th: 
        df_images_clean = df_images_clean[df_images_clean['max_detection_conf'] > treshold]
        
    if save_csv: df_images_clean.to_csv(f'megadetector_image_detection_bbox_th{str(treshold).replace(".", "")}.csv')

    return df_images_clean
In [ ]:
df_images_clean = get_clean_dataframe_from_json(conf_threshold, save_csv=False, filter_th=False)
df_images_clean
Out[ ]:
file max_detection_conf category conf bbox
image_name
ZJ000000 ZJ000000.jpg 0.690 animal 0.690 [0.1093, 0.5888, 0.0802, 0.1851]
ZJ000001 ZJ000001.jpg 0.813 animal 0.813 [0.5604, 0, 0.1333, 0.9685]
ZJ000002 ZJ000002.jpg 0.612 animal 0.612 [0.5093, 0.7777, 0.1281, 0.1777]
ZJ000003 ZJ000003.jpg 0.686 animal 0.686 [0, 0.6277, 0.214, 0.3194]
ZJ000004 ZJ000004.jpg 0.476 animal 0.476 [0.5031, 0.5671, 0.1156, 0.2955]
... ... ... ... ... ...
ZJ016483 ZJ016483.jpg NaN NaN NaN NaN
ZJ016484 ZJ016484.jpg 0.528 animal 0.528 [0.6171, 0, 0.3828, 0.9527]
ZJ016485 ZJ016485.jpg 0.151 animal 0.151 [0.4296, 0.7972, 0.214, 0.1583]
ZJ016486 ZJ016486.jpg 0.264 animal 0.264 [0.125, 0.5518, 0.09687, 0.1]
ZJ016487 ZJ016487.jpg 0.896 animal 0.896 [0.6671, 0.4999, 0.3328, 0.4166]

16491 rows × 5 columns

Unterschiedliche Shapes zwischen df_images und df_images_clean -> 16488 und 16491 ?

In [ ]:
df_images[~df_images['file'].isin(df_images_clean['file'])]
Out[ ]:
file max_detection_conf detections
In [ ]:
df_images_clean[~df_images_clean['file'].isin(df_images['file'])]
Out[ ]:
file max_detection_conf category conf bbox
image_name

Untersuche Kategorien¶

Das Modell des Megadetectors unterscheidet zwischen drei Kategorien: Animal, Person, Vehicle

In [ ]:
df_images_clean['category'].unique().to_list()
Out[ ]:
['animal', nan, 'person', 'vehicle']
In [ ]:
df_images_clean['category'].value_counts().plot.bar()
cat_na = df_images_clean.shape[0]- df_images_clean['category'].value_counts().sum()
plt.title(f'Verteilung der detektierten Kategorien, na:{cat_na}')
plt.tight_layout()
if save_plots: plt.savefig('./plots/dist_detection_classes.png')
plt.show()
In [ ]:
df_images_clean[df_images_clean['category'] == 'animal']['max_detection_conf'].plot.hist()
plt.title('Verteilung von max_detection_conf für Kategorie 1 (Animal)')
plt.xlabel('max_detection_conf')
plt.tight_layout()
if save_plots: plt.savefig('./plots/dist_conf_animal.png')
plt.show()
In [ ]:
df_images_clean[df_images_clean['category'] == 'person']['max_detection_conf'].plot.hist()
plt.title('Verteilung von max_detection_conf für Kategorie 2 (Person)')
plt.xlabel('max_detection_conf')
plt.tight_layout()
if save_plots: plt.savefig('./plots/dist_conf_person.png')
plt.show()
In [ ]:
df_images_clean[df_images_clean['category'] == 'vehicle']['max_detection_conf'].plot.hist()
plt.title('Verteilung von max_detection_conf für Kategorie 3 (vehicle)')
plt.xlabel('max_detection_conf')
plt.tight_layout()
if save_plots: plt.savefig('./plots/dist_conf_vehicle.png')
plt.show()

Prüfe einzelne Bilder für die Klassen person und vehicle¶

Bilder aus den Megadetector Vorhersagen

In [ ]:
lst_img_cat1 = df_images_clean[df_images_clean['category'] == 'animal']['file']
lst_img_cat1 = lst_img_cat1.reset_index(drop=True)
lst_img_cat1 = [image_name.replace('.jpg', '') for image_name in lst_img_cat1]
lst_img_cat1

lst_img_cat2 = df_images_clean[df_images_clean['category'] == 'person']['file']
lst_img_cat2 = lst_img_cat2.reset_index(drop=True)
lst_img_cat2 = [image_name.replace('.jpg', '') for image_name in lst_img_cat2]
lst_img_cat2

lst_img_cat3 = df_images_clean[df_images_clean['category'] == 'vehicle']['file']
lst_img_cat3 = lst_img_cat3.reset_index(drop=True)
lst_img_cat3 = [image_name.replace('.jpg', '') for image_name in lst_img_cat3]
lst_img_cat3

path_img_train = '../competition_data/'
path_img_mega = './train_features_detection_th01/'

Random Ansicht person

In [ ]:
random_lst_img_cat2 = random.sample(lst_img_cat2, 6)

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(12, 6))

# iterate through each bad image
for idx, (img_id, ax) in enumerate(zip(random_lst_img_cat2, axes.flat)):
    # get image label
    img_label = train_features_label.loc[img_id]['label']
    # reads the filepath and returns a numpy array
    img = mpimg.imread(path_img_mega + str(img_id).upper() + '_detections.jpg')
    # get category
    cat, conf = df_images_clean.loc[img_id]['category'], df_images_clean.loc[img_id]['max_detection_conf'], 
    # plot etc
    ax.imshow(img)
    ax.set_title(f"{img_id} | {img_label} | {cat} | Conf: {conf:2f}", fontsize=8)

plt.tight_layout()
plt.show() 

Random Ansicht vehicle

In [ ]:
random_lst_img_cat3 = random.sample(lst_img_cat3, 6) 

fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(12, 6))

# iterate through each bad image
for idx, (img_id, ax) in enumerate(zip(random_lst_img_cat3, axes.flat)):
    # get image label
    img_label = train_features_label.loc[img_id]['label']
    # reads the filepath and returns a numpy array
    img = mpimg.imread(path_img_mega + str(img_id).upper() + '_detections.jpg')
    # get category
    cat, conf = df_images_clean.loc[img_id]['category'], df_images_clean.loc[img_id]['max_detection_conf'], 
    # plot etc
    ax.imshow(img)
    ax.set_title(f"{img_id} | {img_label} | {cat} | Conf: {conf:2f}", fontsize=8)

plt.tight_layout()
plt.show()

Random Ansicht animal¶

In [ ]:
random_lst_img_cat1 = random.sample(lst_img_cat1, 12)

fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(15, 15))

# iterate through each bad image
for idx, (img_id, ax) in enumerate(zip(random_lst_img_cat1, axes.flat)):
    # get image label
    img_label = train_features_label.loc[img_id]['label']
    # reads the filepath and returns a numpy array
    img = mpimg.imread(path_img_mega + str(img_id).upper() + '_detections.jpg')
    # get category
    cat, conf = df_images_clean.loc[img_id]['category'], df_images_clean.loc[img_id]['max_detection_conf'], 
    # plot etc
    ax.imshow(img)
    ax.set_title(f"{img_id} | {img_label} | {cat} | Conf: {conf:2f}", fontsize=8)

fig.tight_layout()
plt.show()

Beispiele für Falschklassifikation mit hoher Confidence¶

In [ ]:
missclassification_findings = ['ZJ010981', 'ZJ014854', 'ZJ003542']
random_miss_class= random.sample(missclassification_findings, 3)

fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(12, 12))

# iterate through each bad image
for idx, (img_id, ax) in enumerate(zip(random_miss_class, axes.flat)):
    # get image label
    img_label = train_features_label.loc[img_id]['label']
    # reads the filepath and returns a numpy array
    img = mpimg.imread(path_img_mega + str(img_id).upper() + '_detections.jpg')
    # get category
    cat, conf = df_images_clean.loc[img_id]['category'], df_images_clean.loc[img_id]['max_detection_conf'], 
    # plot etc
    ax.imshow(img)
    ax.set_title(f"{img_id} | {img_label} | {cat} | Conf: {conf:2f}", fontsize=8)

plt.tight_layout()
plt.show()
In [ ]: